# 文件名: server.py
import asyncio
import websockets
import json
import subprocess
import sys

HOST = '127.0.0.1'
WEBSOCKET_PORT = 5000  # WebSocket服务器端口
UDP_PORT = 5001        # 用于接收launch.py完成通知的UDP端口

# 全局变量，用于存储当前连接的WebSocket客户端
clients = set()

# --- UDP服务器部分 ---
class UdpNotificationProtocol(asyncio.DatagramProtocol):
    def __init__(self, connected_clients):
        self.clients = connected_clients
        super().__init__()

    def datagram_received(self, data, addr):
        message = data.decode()
        if message == 'done':
            print(f"收到来自 {addr} 的UDP完成通知。")
            
            # 向所有连接的网页客户端转发“泊车完成”消息
            completion_message = json.dumps({"status": "parking_complete"})
            for client in self.clients:
                # 使用asyncio.create_task确保发送不会阻塞UDP监听
                asyncio.create_task(client.send(completion_message))
            print("已通过WebSocket向所有客户端转发完成标志。")

# --- WebSocket服务器部分 ---
async def websocket_handler(websocket):
    """处理WebSocket连接和来自网页的指令。"""
    clients.add(websocket)
    print(f"新客户端已连接: {websocket.remote_address} (当前共 {len(clients)} 个)")
    try:
        async for message in websocket:
            try:
                data = json.loads(message)
                action = data.get('action')

                if action == 'start_parking':
                    params = data.get('params', '00')
                    print(f"收到泊车指令，参数: {params}。正在启动 launch.py...")
                    
                    # 启动launch.py脚本，它运行完后会发送UDP通知
                    command = [sys.executable, 'launch.py', params]
                    subprocess.Popen(command)

            except Exception as e:
                print(f"处理WebSocket消息时出错: {e}")
    finally:
        clients.remove(websocket)
        print(f"客户端已断开: {websocket.remote_address} (剩余 {len(clients)} 个)")


async def main():
    """同时启动WebSocket和UDP服务器。"""
    # 获取事件循环
    loop = asyncio.get_running_loop()

    # 启动WebSocket服务器
    websocket_server = await websockets.serve(websocket_handler, HOST, WEBSOCKET_PORT)
    print(f"WebSocket控制服务器已在 ws://{HOST}:{WEBSOCKET_PORT} 启动")

    # 启动UDP服务器来监听完成通知
    udp_transport, _ = await loop.create_datagram_endpoint(
        lambda: UdpNotificationProtocol(clients),
        local_addr=(HOST, UDP_PORT))
    print(f"UDP通知监听器已在 {HOST}:{UDP_PORT} 启动")

    try:
        # 永远运行下去
        await asyncio.Future()
    finally:
        udp_transport.close()
        websocket_server.close()
        await websocket_server.wait_closed()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n服务器已关闭。")